using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
namespace Microsoft.Phone.Controls
{
	internal class PopupHelper
	{
		private const double PopupOffset = 2.0;
		private bool _hasControlLoaded;
		public event EventHandler Closed;
		public event EventHandler FocusChanged;
		public event EventHandler UpdateVisualStates;
		public bool UsesClosingVisualState
		{
			get;
			private set;
		}
		private Control Parent
		{
			get;
			set;
		}
		private Canvas OutsidePopupCanvas
		{
			get;
			set;
		}
		private Canvas PopupChildCanvas
		{
			get;
			set;
		}
		public double MaxDropDownHeight
		{
			get;
			set;
		}
		public Popup Popup
		{
			get;
			private set;
		}
		public bool IsOpen
		{
			get
			{
				return this.Popup.get_IsOpen();
			}
			set
			{
				this.Popup.set_IsOpen(value);
			}
		}
		private FrameworkElement PopupChild
		{
			get;
			set;
		}
		public PopupHelper(Control parent)
		{
			this.Parent = parent;
		}
		public PopupHelper(Control parent, Popup popup) : this(parent)
		{
			this.Popup = popup;
		}
		private MatrixTransform GetControlMatrixTransform()
		{
			MatrixTransform result;
			try
			{
				result = (this.Parent.TransformToVisual(null) as MatrixTransform);
			}
			catch
			{
				this.OnClosed(EventArgs.Empty);
				result = null;
			}
			return result;
		}
		private static Point MatrixTransformPoint(MatrixTransform matrixTransform, Thickness margin)
		{
			double num = matrixTransform.get_Matrix().get_OffsetX() + margin.get_Left();
			double num2 = matrixTransform.get_Matrix().get_OffsetY() + margin.get_Top();
			return new Point(num, num2);
		}
		private Size GetControlSize(Thickness margin, Size? finalSize)
		{
			double num = (finalSize.get_HasValue() ? finalSize.get_Value().get_Width() : this.Parent.get_ActualWidth()) - margin.get_Left() - margin.get_Right();
			double num2 = (finalSize.get_HasValue() ? finalSize.get_Value().get_Height() : this.Parent.get_ActualHeight()) - margin.get_Top() - margin.get_Bottom();
			return new Size(num, num2);
		}
		private Thickness GetMargin()
		{
			Thickness? thickness = this.Popup.get_Resources().get_Item("PhoneTouchTargetOverhang") as Thickness?;
			if (thickness.get_HasValue())
			{
				return thickness.get_Value();
			}
			return new Thickness(0.0);
		}
		private static bool IsChildAbove(Size displaySize, Size controlSize, Point controlOffset)
		{
			double y = controlOffset.get_Y();
			double num = displaySize.get_Height() - controlSize.get_Height() - y;
			return y > num;
		}
		private static double Min0(double x, double y)
		{
			return Math.Max(Math.Min(x, y), 0.0);
		}
		private Size AboveChildSize(Size controlSize, Point controlPoint)
		{
			double width = controlSize.get_Width();
			double x = controlPoint.get_Y() - 2.0;
			double maxDropDownHeight = this.MaxDropDownHeight;
			double num = PopupHelper.Min0(x, maxDropDownHeight);
			return new Size(width, num);
		}
		private Size BelowChildSize(Size displaySize, Size controlSize, Point controlPoint)
		{
			double width = controlSize.get_Width();
			double x = displaySize.get_Height() - controlSize.get_Height() - controlPoint.get_Y() - 2.0;
			double maxDropDownHeight = this.MaxDropDownHeight;
			double num = PopupHelper.Min0(x, maxDropDownHeight);
			return new Size(width, num);
		}
		private Point AboveChildPoint(Thickness margin)
		{
			double left = margin.get_Left();
			double num = margin.get_Top() - this.PopupChild.get_ActualHeight() - 2.0;
			return new Point(left, num);
		}
		private static Point BelowChildPoint(Thickness margin, Size controlSize)
		{
			double left = margin.get_Left();
			double num = margin.get_Top() + controlSize.get_Height() + 2.0;
			return new Point(left, num);
		}
		public void Arrange(Size? finalSize)
		{
			if (this.Popup == null || this.PopupChild == null || Application.get_Current() == null || this.OutsidePopupCanvas == null || Application.get_Current().get_Host() == null || Application.get_Current().get_Host().get_Content() == null)
			{
				return;
			}
			PhoneApplicationFrame phoneApplicationFrame;
			if (!PhoneHelper.TryGetPhoneApplicationFrame(out phoneApplicationFrame))
			{
				return;
			}
			Size usefulSize = phoneApplicationFrame.GetUsefulSize();
			Thickness margin = this.GetMargin();
			Size controlSize = this.GetControlSize(margin, finalSize);
			MatrixTransform controlMatrixTransform = this.GetControlMatrixTransform();
			if (controlMatrixTransform == null)
			{
				return;
			}
			Point point = PopupHelper.MatrixTransformPoint(controlMatrixTransform, margin);
			Size sipUncoveredSize = phoneApplicationFrame.GetSipUncoveredSize();
			bool flag;
			Size size = (flag = PopupHelper.IsChildAbove(sipUncoveredSize, controlSize, point)) ? this.AboveChildSize(controlSize, point) : this.BelowChildSize(sipUncoveredSize, controlSize, point);
			if (usefulSize.get_Width() != 0.0 && usefulSize.get_Height() != 0.0)
			{
				if (size.get_Height() != 0.0)
				{
					Point point2 = flag ? this.AboveChildPoint(margin) : PopupHelper.BelowChildPoint(margin, controlSize);
					this.Popup.set_HorizontalOffset(0.0);
					this.Popup.set_VerticalOffset(0.0);
					FrameworkElement arg_161_0 = this.PopupChild;
					FrameworkElement arg_15A_0 = this.PopupChild;
					double width;
					this.PopupChild.set_MinWidth(width = controlSize.get_Width());
					double width2;
					arg_15A_0.set_MaxWidth(width2 = width);
					arg_161_0.set_Width(width2);
					this.PopupChild.set_MinHeight(0.0);
					this.PopupChild.set_MaxHeight(size.get_Height());
					this.PopupChild.set_HorizontalAlignment(0);
					this.PopupChild.set_VerticalAlignment(0);
					Canvas.SetLeft(this.PopupChild, point2.get_X());
					Canvas.SetTop(this.PopupChild, point2.get_Y());
					this.OutsidePopupCanvas.set_Width(controlSize.get_Width());
					this.OutsidePopupCanvas.set_Height(usefulSize.get_Height());
					Matrix matrix = controlMatrixTransform.get_Matrix();
					Matrix matrix2;
					matrix.Invert(out matrix2);
					controlMatrixTransform.set_Matrix(matrix2);
					this.OutsidePopupCanvas.set_RenderTransform(controlMatrixTransform);
					return;
				}
			}
		}
		private void OnClosed(EventArgs e)
		{
			EventHandler closed = this.Closed;
			if (closed != null)
			{
				closed.Invoke(this, e);
			}
		}
		private void OnPopupClosedStateChanged(object sender, VisualStateChangedEventArgs e)
		{
			if (e != null && e.get_NewState() != null && e.get_NewState().get_Name() == "PopupClosed")
			{
				if (this.Popup != null)
				{
					this.Popup.set_IsOpen(false);
				}
				this.OnClosed(EventArgs.Empty);
			}
		}
		public void BeforeOnApplyTemplate()
		{
			if (this.UsesClosingVisualState)
			{
				VisualStateGroup visualStateGroup = VisualStates.TryGetVisualStateGroup(this.Parent, "PopupStates");
				if (visualStateGroup != null)
				{
					visualStateGroup.remove_CurrentStateChanged(new EventHandler<VisualStateChangedEventArgs>(this.OnPopupClosedStateChanged));
					this.UsesClosingVisualState = false;
				}
			}
			if (this.Popup != null)
			{
				this.Popup.remove_Closed(new EventHandler(this.Popup_Closed));
			}
		}
		public void AfterOnApplyTemplate()
		{
			if (this.Popup != null)
			{
				this.Popup.add_Closed(new EventHandler(this.Popup_Closed));
			}
			VisualStateGroup visualStateGroup = VisualStates.TryGetVisualStateGroup(this.Parent, "PopupStates");
			if (visualStateGroup != null)
			{
				visualStateGroup.add_CurrentStateChanged(new EventHandler<VisualStateChangedEventArgs>(this.OnPopupClosedStateChanged));
				this.UsesClosingVisualState = true;
			}
			if (this.Popup != null)
			{
				this.PopupChild = (this.Popup.get_Child() as FrameworkElement);
				if (this.PopupChild != null && !this._hasControlLoaded)
				{
					this._hasControlLoaded = true;
					this.PopupChildCanvas = new Canvas();
					this.Popup.set_Child(this.PopupChildCanvas);
					this.OutsidePopupCanvas = new Canvas();
					this.OutsidePopupCanvas.set_Background(new SolidColorBrush(Colors.get_Transparent()));
					this.OutsidePopupCanvas.add_MouseLeftButtonDown(new MouseButtonEventHandler(this.OutsidePopup_MouseLeftButtonDown));
					this.PopupChildCanvas.get_Children().Add(this.OutsidePopupCanvas);
					this.PopupChildCanvas.get_Children().Add(this.PopupChild);
					this.PopupChild.add_GotFocus(new RoutedEventHandler(this.PopupChild_GotFocus));
					this.PopupChild.add_LostFocus(new RoutedEventHandler(this.PopupChild_LostFocus));
					this.PopupChild.add_MouseEnter(new MouseEventHandler(this.PopupChild_MouseEnter));
					this.PopupChild.add_MouseLeave(new MouseEventHandler(this.PopupChild_MouseLeave));
					this.PopupChild.add_SizeChanged(new SizeChangedEventHandler(this.PopupChild_SizeChanged));
				}
			}
		}
		private void PopupChild_SizeChanged(object sender, SizeChangedEventArgs e)
		{
			this.Arrange(default(Size?));
		}
		private void OutsidePopup_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
		{
			if (this.Popup != null)
			{
				this.Popup.set_IsOpen(false);
			}
		}
		private void Popup_Closed(object sender, EventArgs e)
		{
			this.OnClosed(EventArgs.Empty);
		}
		private void OnFocusChanged(EventArgs e)
		{
			EventHandler focusChanged = this.FocusChanged;
			if (focusChanged != null)
			{
				focusChanged.Invoke(this, e);
			}
		}
		private void OnUpdateVisualStates(EventArgs e)
		{
			EventHandler updateVisualStates = this.UpdateVisualStates;
			if (updateVisualStates != null)
			{
				updateVisualStates.Invoke(this, e);
			}
		}
		private void PopupChild_GotFocus(object sender, RoutedEventArgs e)
		{
			this.OnFocusChanged(EventArgs.Empty);
		}
		private void PopupChild_LostFocus(object sender, RoutedEventArgs e)
		{
			this.OnFocusChanged(EventArgs.Empty);
		}
		private void PopupChild_MouseEnter(object sender, MouseEventArgs e)
		{
			this.OnUpdateVisualStates(EventArgs.Empty);
		}
		private void PopupChild_MouseLeave(object sender, MouseEventArgs e)
		{
			this.OnUpdateVisualStates(EventArgs.Empty);
		}
	}
}
